﻿
namespace Huirui.Cavan.Core.Extension
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Reflection;
    using log4net;

    /// <summary>
    ///     Extensions available on every place of the framework.
    /// </summary>
    public static partial class Ext
    {
        #region object .Log()
        /// <summary>
        ///     provides direct access to ILog object based on caller's Type.
        ///     It allows to switch off logging for libraries independently
        /// </summary>
        /// <returns></returns>
        public static ILog Log(this object value)
        {
            Contract.Requires(value.Is(),
                " Cannot create Logger for 'null' object! Provide instance instead for logging as reporter. ");
            return value.GetType().Log();
        }
        #endregion object .Log()

        #region Type .Log()
        /// <summary>
        ///     Direct access to ILog object based on caller (Type).
        /// </summary>
        /// <returns></returns>
        public static ILog Log(this Type type)
        {
            return LogManager.GetLogger(type);
        }
        #endregion Type .Log()

        #region Type GetDescriptors
        /// <summary>
        ///     returns (Cached) information about "item" properties
        /// </summary>
        /// <returns></returns>
        public static IDictionary<string, PropertyDescriptor> GetPropertyDescriptors(this Type type)
        {
            Contract.Requires(type.Is(), "Type cannot be null");
            return TypeDescriptor.GetProperties(type)
                .Cast<PropertyDescriptor>()
                .ToDictionary(
                    pd => pd.Name,
                    pd => pd);
        }

        public static bool HasType(this Type toBeCompared, Type type)
        {
            if (toBeCompared.IsNull()
                || type.IsNull())
            {
                return false;
            }
            if (toBeCompared.IsEquivalentTo(type))
            {
                return true;
            }
            if (type.IsInterface)
            {
                return toBeCompared.GetInterfaces().Any(i => i.IsEquivalentTo(type));
            }
            return false;
        }
        #endregion Type GetDescriptors

        #region Type Attribute
        /// <summary>
        ///     Gets the custom attribute.
        /// </summary>
        /// <typeparam name = "TAttributeType">The type of the ttribute type.</typeparam>
        /// <param name = "type">The type.</param>
        /// <param name = "inherit">if set to <c>true</c> [inherit].</param>
        /// <returns></returns>
        public static TAttributeType GetCustomAttribute<TAttributeType>(this ICustomAttributeProvider type, bool inherit)
            where TAttributeType : class
        {
            Contract.Requires(type.Is(),
                "MemberInfo 'type' argument cannot be null when searching for 'TAttributeType' Attribute.");
            var customAttributes = type.GetCustomAttributes(typeof(TAttributeType), inherit);
            if (customAttributes.Any())
            {
                return (TAttributeType)customAttributes[0];
            }
            return default(TAttributeType);
        }
        #endregion Type Attribute
    }
}